home *** CD-ROM | disk | FTP | other *** search
/ Chip: Internet / Chip Internet.iso / viewer / ghost / gsview.c < prev    next >
C/C++ Source or Header  |  1993-07-29  |  37KB  |  1,313 lines

  1. /*
  2.  * gsview.c -- Main module of GSVIEW.EXE, a graphical interface for 
  3.  *             MS-Windows Ghostscript
  4.  * Copyright (C) 1993  Russell Lang
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *   Author: Russell Lang
  21.  * Internet: rjl@monu1.cc.monash.edu.au
  22.  */
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <mmsystem.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <dir.h>
  35. #include <io.h>
  36. #define NeedFunctionPrototypes 1
  37. #include "ps.h"
  38. #include "gsview.h"
  39.  
  40. char szAppName[MAXSTR];            /* application name - for title bar */
  41. const char szClassName[] = "gsview_class";
  42. const char szScratch[] = "gsview";    /* temporary filename prefix */
  43.  
  44. HWND hwndimg;            /* gsview main window */
  45. HWND hDlgModeless;        /* any modeless dialog box */
  46. HWND hwndtext;            /* gswin text window */
  47. HWND hwndimgchild;        /* gswin image child window */
  48. HINSTANCE phInstance;        /* instance of gsview */
  49. HINSTANCE gswin_hinst;        /* instance of gswin */
  50. int bitmap_scrollx=0;        /* offset from bitmap to origin of child window */
  51. int bitmap_scrolly=0;
  52. int bitmap_width;        /* size of gswin bitmap in pixels */
  53. int bitmap_height;
  54.  
  55. /* these can be saved in the INI file */
  56. char szGSwin[128];        /* command to invoke gswin */
  57. POINT img_origin;        /* gsview window origin */
  58. POINT img_size;            /* gsview window size */
  59. BOOL quick;            /* use quick opening (don't reload gswin) */
  60. BOOL settings;            /* save settings on exit */
  61. BOOL button_show;        /* show buttons bar */
  62. int media;            /* IDM_LETTER etc. */
  63. char medianame[32];        /* name of media */
  64. int user_width, user_height;    /* User Defined media size */
  65. BOOL epsf_clip;            /* make bitmap size of epsf bounding box */
  66. BOOL epsf_warn;            /* write warning messages if operators incompatible with EPS are used */
  67. BOOL redisplay;            /* redisplay on resize */
  68. BOOL safer;            /* use -dSAFER option */
  69. int orientation;        /* IDM_PORTRAIT, IDM_LANDSCAPE etc. */
  70. BOOL swap_landscape;        /* swap IDM_LANDSCAPE & IDM_SEASCAPE */
  71. float xdpi, ydpi;        /* resolution of gswin bitmap */
  72. UINT timeout;            /* default timeout period in 1 sec units */
  73. BOOL save_dir;            /* remember current directory for next time */
  74. char device_name[32];        /* printer name */
  75. char device_resolution[32];    /* printer resolution */
  76.  
  77. struct sound_s sound[NUMSOUND] = {
  78.     {"SoundOutputPage", IDS_SNDPAGE, ""},
  79.     {"SoundNoPage", IDS_SNDNOPAGE, BEEP},
  80.     {"SoundNoNumbering", IDS_SNDNONUMBER, ""},
  81.     {"SoundNotOpen", IDS_SNDNOTOPEN, ""},
  82.     {"SoundError", IDS_SNDERROR, BEEP},
  83.     {"SoundTimeout", IDS_SNDTIMEOUT, ""},
  84.     {"SoundStart", IDS_SNDSTART, ""},
  85.     {"SoundExit", IDS_SNDEXIT, ""},
  86. };
  87.  
  88.  
  89. /* initialised in init.c */
  90. BOOL is_win31 = FALSE;        /* To allow selective use of win 3.1 features */
  91. char szHelpName[MAXSTR];    /* buffer for building help filename */
  92. char szHelpTopic[48];        /* topic for OFN_SHOWHELP */
  93. UINT help_message;        /* message sent by OFN_SHOWHELP */
  94. HMENU hmenu;            /* main menu */
  95. HACCEL haccel;            /* menu accelerators */
  96. HCURSOR hcWait;
  97. POINT img_offset;        /* offset to gswin child window */
  98. POINT info_file;        /* position of file information */
  99. POINT info_page;        /* position of page information */
  100. RECT  info_rect;        /* position and size of brief info area */
  101. RECT  info_coord;        /* position and size of coordinate information */
  102. RECT  button_rect;        /* position and size of button area */
  103.  
  104. BOOL prev_in_child;        /* true if cursor previously in gswin child window */
  105. BOOL waiting = FALSE;        /* true when 'wait' to be displayed in info area */
  106. BOOL page_ready = FALSE;    /* true when gswin has sent an OUTPUT_PAGE and is waiting for NEXT_PAGE */
  107. BOOL saved = FALSE;        /* true if interpreter state currently saved in /gssave */
  108. BOOL epsf_clipped;        /* clipping this page? */
  109. int page_skip = 5;        /* number of pages to skip in IDM_NEXTSKIP or IDM_PREVSKIP */
  110. int page_extra;            /* extra pages to skip */
  111. BOOL debug = FALSE;        /* /D command line option used */
  112. HINSTANCE hlib_mmsystem;    /* DLL containing sndPlaySound function */
  113. FPSPS lpfnSndPlaySound;        /* pointer to sndPlaySound function if loaded */
  114.  
  115. /* timer used for open, close, display & print timeouts */
  116. BOOL bTimeout;            /* true if timeout occured */
  117. BOOL bTimerSet;            /* true if TIMER running */
  118. #define ID_MYTIMER 1
  119. UINT timeout_count;
  120.  
  121. /* document manipulation */
  122. struct document *doc;    /* DSC structure.  NULL if not DSC */
  123. int pagenum;        /* current page number */
  124. char dfname[MAXSTR];    /* name of selected document file */
  125. char efname[MAXSTR];    /* name of temporary file containing PS extracted 
  126.                            from DOS EPS file */
  127. FILE *dfile;        /* selected file */
  128. FILE *cfile;        /* command file (pipe) */
  129. BOOL is_ctrld;        /* TRUE if DSC except for ctrl+D at start of file */
  130. int preview;        /* preview type IDS_EPSF, IDS_EPSI, etc. */
  131. struct page_list_s page_list;    /*  page selection for print/extract */
  132.  
  133. /* local functions */
  134. BOOL draw_button(DRAWITEMSTRUCT FAR *lpdis);
  135. BOOL in_child_client_area(void);
  136. BOOL in_client_area(void);
  137. BOOL in_info_area(void);
  138. void info_paint(HWND);
  139. void gsview_close(void);
  140. int gsview_command(WORD);
  141. BOOL not_open(void);
  142. BOOL not_dsc(void);
  143.  
  144. int PASCAL 
  145. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
  146. {
  147.     MSG msg;
  148.  
  149.     /* copy the hInstance into a variable so it can be used */
  150.     phInstance = hInstance;
  151.  
  152.     LoadString(hInstance, IDS_TITLE, szAppName, sizeof(szAppName));
  153.     if (hPrevInstance) {
  154.         /* don't run more than one copy */
  155.         /* because we can't run more than one Ghostscript */
  156.         gsview_init0(lpszCmdLine);
  157.         return FALSE;
  158.     }
  159.  
  160.     gsview_init1(lpszCmdLine);
  161.     ShowWindow(hwndimg, cmdShow);
  162.     
  163.     while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
  164.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  165.             if (!TranslateAccelerator(hwndimg, haccel, &msg)) {
  166.             TranslateMessage(&msg);
  167.             DispatchMessage(&msg);
  168.             }
  169.         }
  170.     }
  171.  
  172.     play_sound(SOUND_EXIT);
  173.     gsview_close();
  174.      WinHelp(hwndimg,szHelpName,HELP_QUIT,(DWORD)NULL);
  175.     if (is_win31 && (hlib_mmsystem != (HINSTANCE)NULL))
  176.         FreeLibrary(hlib_mmsystem);
  177.     return 0;
  178. }
  179.  
  180.  
  181. /* parent overlapped window */
  182. LRESULT CALLBACK _export
  183. WndImgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  184. {
  185. RECT rect;
  186.  
  187.     if (message == WM_GSVIEW) {
  188.     switch(wParam) {
  189.         case HWND_TEXT:
  190.         /* lParam = handle to Ghostscript Borland EasyWin window */
  191.         hwndtext = (HWND)lParam;
  192.         break;
  193.         case HWND_IMGCHILD:
  194.         /* lParam = handle to Ghostscript image child window */
  195.         hwndimgchild = (HWND)lParam;
  196.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  197.             SetClassCursor(hwndimgchild, LoadCursor((HINSTANCE)NULL, IDC_CROSS));
  198.             GetClientRect(hwnd, &rect);
  199.             SetWindowPos(hwndimgchild, (HWND)NULL, rect.left+img_offset.x, rect.top+img_offset.y,
  200.             rect.right-img_offset.x, rect.bottom-img_offset.y, 
  201.             SWP_NOZORDER | SWP_NOACTIVATE);
  202.         }
  203.         break;
  204.         case GSWIN_CLOSE:
  205.         /* something is closing gswin */
  206.         gswin_hinst = (HINSTANCE)NULL;
  207.         hwndimgchild = (HWND)NULL;
  208.         hwndtext = (HWND)NULL;
  209.         bitmap_scrollx = bitmap_scrolly = 0;
  210.         page_ready = FALSE;
  211.         page_extra = 0;
  212.         saved = FALSE;
  213.         pipeclose();
  214.         clear_timer();
  215.         info_wait(FALSE);
  216.         break;
  217.         case OUTPUT_PAGE:
  218.         /* showpage has just been called */
  219.         clear_timer();
  220.         play_sound(SOUND_PAGE);
  221.         if (IsIconic(hwndimg))    /* useless as an Icon so fix it */
  222.             ShowWindow(hwndimg, SW_SHOWNORMAL);
  223.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  224.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  225.             /* don't erase background - the bitmap will cover it anyway */
  226.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  227.             UpdateWindow(hwndimgchild);
  228.             }
  229.         }
  230.         page_ready = TRUE;
  231.         info_wait(FALSE);
  232.         if (page_extra) {
  233.             PostMessage(hwndimg, WM_COMMAND, IDM_SKIP, (LPARAM)0);
  234.         }
  235.         break;
  236.         case SYNC_OUTPUT:
  237.         /* time to redraw window */
  238.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  239.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  240.             /* don't erase background - the bitmap will cover it anyway */
  241.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  242.             UpdateWindow(hwndimgchild);
  243.             }
  244.         }
  245.         break;
  246.         case SCROLL_POSITION:
  247.         /* User scrolled image window.  
  248.          * lParam = offsets to top left of image window
  249.          * we use these to display coordinates */
  250.         bitmap_scrollx = LOWORD(lParam);
  251.         bitmap_scrolly = HIWORD(lParam);
  252.         InvalidateRect(hwndimg, &info_coord, FALSE);
  253.         UpdateWindow(hwndimg);
  254.         break;
  255.         case PIPE_REQUEST:
  256.         piperequest();
  257.         break;
  258.         default:
  259.         gserror(0, "Unknown Message", MB_ICONEXCLAMATION, -1);
  260.     }
  261.     return 0;
  262.     }
  263.     else if (message == help_message) {
  264.     WinHelp(hwndimg,szHelpName,HELP_KEY,(DWORD)szHelpTopic);
  265.     return 0;
  266.     } else
  267.     switch(message) {
  268.     case WM_CREATE:
  269.         hwndimg = hwnd;
  270.         gsview_create();
  271.         /* Enable Drag Drop */
  272.         if (is_win31)
  273.             DragAcceptFiles(hwnd, TRUE);
  274.         break;
  275.     case WM_DESTROY:
  276.         /* disable Drag Drop */
  277.         if (is_win31)
  278.             DragAcceptFiles(hwnd, FALSE);
  279.         gsview_close();
  280.         PostQuitMessage(0);
  281.         break;
  282.     case WM_ENDSESSION:
  283.         if (wParam)
  284.             gsview_close();
  285.         return 0;
  286.     case WM_TIMER:
  287.         if (wParam == ID_MYTIMER) {
  288.             timeout_count--;
  289.             if (timeout_count <= 0) {
  290.             clear_timer();
  291.             bTimeout = TRUE;
  292.             gserror(IDS_TIMEOUT, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  293.             info_wait(FALSE);
  294.             }
  295.         }
  296.         break;
  297.     case WM_DROPFILES:
  298.         if (is_win31) {
  299.             LPSTR szFile;
  300.             int i, cFiles, length;
  301.             HDROP hdrop = (HDROP)wParam;
  302.             cFiles = DragQueryFile(hdrop, 0xffff, (LPSTR)NULL, 0);
  303.             for (i=0; i<cFiles; i++) {
  304.             length = DragQueryFile(hdrop, i, (LPSTR)NULL, 0);
  305.             szFile = GlobalAllocPtr(GHND, length+1);
  306.             if (szFile) {
  307.                 DragQueryFile(hdrop, i, szFile, MAXSTR);
  308.                 /* it doesn't work if we call gsview_display directly */
  309.                 PostMessage(hwnd, WM_COMMAND, IDM_DROP, (LPARAM)szFile);
  310.             }
  311.             }
  312.             DragFinish(hdrop);
  313.         }
  314.         break;
  315.     case WM_INITMENU:
  316.         if (hmenu == (HMENU)wParam) {
  317.             HMENU hmenuedit = GetSubMenu(hmenu,1);
  318.             if (hwndimgchild  && IsWindow(hwndimgchild))
  319.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_ENABLED);
  320.             else
  321.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_DISABLED | MF_GRAYED);
  322.             if (OpenClipboard(hwnd)) {
  323.             if (IsClipboardFormatAvailable(CF_DIB))
  324.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_ENABLED);
  325.             else
  326.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_DISABLED | MF_GRAYED);
  327.             if (IsClipboardFormatAvailable(CF_DIB) || 
  328.                 IsClipboardFormatAvailable(CF_BITMAP)) 
  329.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_ENABLED);
  330.             else
  331.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_DISABLED | MF_GRAYED);
  332.             /* Make EPS sub menu */
  333.             if ((IsClipboardFormatAvailable(CF_DIB) ||
  334.                  IsClipboardFormatAvailable(CF_BITMAP)) 
  335.                 && (doc != (struct document *)NULL) && doc->epsf)
  336.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_ENABLED);
  337.             else
  338.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  339.             /* Extract EPS sub menu */
  340.             if ( (preview == IDS_EPST) || (preview == IDS_EPSW) )
  341.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_ENABLED);
  342.             else
  343.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  344.             CloseClipboard();
  345.             }
  346.             return 0;
  347.         }
  348.         break;
  349.     case WM_COMMAND:
  350.         if (LOWORD(wParam) == IDM_DROP) {
  351.             HGLOBAL hglobal;
  352.             char buf[MAXSTR];
  353.             if (lstrlen((LPSTR)lParam) < sizeof(buf))
  354.             lstrcpy(buf, (LPSTR)lParam);
  355.             else
  356.             buf[0] = '\0';
  357.             hglobal = (HGLOBAL)LOWORD(GlobalHandle(SELECTOROF(lParam)));
  358.             GlobalUnlock(hglobal);
  359.             GlobalFree(hglobal);
  360.             if ((buf[0] == '-') || (buf[0] == '/')) {
  361.             switch (toupper(buf[1])) {
  362.                 case 'P':
  363.                       gsview_selectfile(buf+2);
  364.                       gsview_print(FALSE);
  365.                   break;
  366.                 case 'F':
  367.                       gsview_selectfile(buf+2);
  368.                       gsview_print(TRUE);
  369.                   break;
  370.                 case 'S':
  371.                   if (buf[2] != ' ') {
  372.                 char *fname;
  373.                 /* skip over port name */
  374.                 for (fname=buf+2; *fname && *fname!=' '; fname++)
  375.                   /* nothing */ ;
  376.                     /* skip blanks until file name */
  377.                     if (*fname) {
  378.                       *fname++ = '\0'; /* place null after port name */
  379.                       for (; *fname==' '; fname++)
  380.                         /* nothing */ ;
  381.                     }
  382.                     if (*fname) {
  383.                         /* found both filename and port */
  384.                         gsview_spool(fname, buf+2);
  385.                         break;
  386.                     }
  387.                   }
  388.                       gsview_spool(buf+2, (char *)NULL);
  389.                   break;
  390.                 default:
  391.                   gserror(IDS_BADCLI, buf, MB_ICONEXCLAMATION, SOUND_ERROR);
  392.             }
  393.             }
  394.             else
  395.                 gsview_displayfile(buf);
  396.         }
  397.         else {
  398.             if (GetNotification(wParam,lParam) != BN_DOUBLECLICKED)
  399.                 gsview_command(LOWORD(wParam));
  400.         }
  401.         return 0;
  402.     case WM_KEYDOWN:
  403.     case WM_KEYUP:
  404.         /* pass on key presses so that child window scroll bars work */
  405.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  406.             SendMessage(hwndimgchild, message, wParam, lParam);
  407.             return 0;
  408.         }
  409.         break;
  410.     case WM_SIZE:
  411.         /* make child window fill client area */
  412.         if (wParam != SIZE_MINIMIZED  && hwndimgchild !=(HWND)NULL && IsWindow(hwndimgchild))
  413.             SetWindowPos(hwndimgchild, (HWND)NULL, img_offset.x, img_offset.y,
  414.             LOWORD(lParam)-img_offset.x, HIWORD(lParam)-img_offset.y, 
  415.             SWP_NOZORDER | SWP_NOACTIVATE);
  416.         /* save window size for INIFILE */
  417.         if (wParam == SIZE_RESTORED) {
  418.             GetWindowRect(hwnd,&rect);
  419.             img_size.x = rect.right-rect.left;
  420.             img_size.y = rect.bottom-rect.top;
  421.         }
  422.         return 0;
  423.     case WM_MOVE:
  424.         /* save window position for INIFILE */
  425.         if (!IsIconic(hwnd) && !IsZoomed(hwnd)) {
  426.             GetWindowRect(hwnd,&rect);
  427.             img_origin.x = rect.left;
  428.             img_origin.y = rect.top;
  429.         }
  430.         return 0;
  431.     case WM_SETCURSOR:
  432.         /* if waiting, display hourglass cursor over our window */
  433.         if (waiting) {
  434.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  435.             if (in_child_client_area() || in_info_area() || (LOWORD(lParam)==HTMENU)) {
  436.                 SetCursor(hcWait);
  437.                 return TRUE;
  438.                 }
  439.             }
  440.             else {
  441.                 SetCursor(hcWait);
  442.                 return TRUE;
  443.             }
  444.         }
  445.         /* track cursor and display coordinates if in child window */
  446.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  447.             if (in_child_client_area() || prev_in_child) {
  448.             /* update coordinate info */
  449.             InvalidateRect(hwndimg, &info_coord, FALSE);
  450.             UpdateWindow(hwndimg);
  451.             }
  452.             prev_in_child = in_child_client_area();
  453.         }
  454.         break;
  455.     case WM_PARENTNOTIFY:
  456.         if (hDlgModeless && (wParam == WM_LBUTTONDOWN))
  457.             if (in_child_client_area())
  458.                 SendMessage(hDlgModeless, WM_COMMAND, BB_CLICK, lParam);
  459.         break;
  460.     case WM_PAINT:
  461.         info_paint(hwnd);
  462.         return 0;
  463.     case WM_MEASUREITEM:
  464.         return 1;
  465.     case WM_DRAWITEM:
  466.         return draw_button((DRAWITEMSTRUCT FAR *)lParam);
  467.     }
  468.     return DefWindowProc(hwnd, message, wParam, lParam);
  469. }
  470.  
  471. /* return TRUE if button drawn */
  472. BOOL
  473. draw_button(DRAWITEMSTRUCT FAR *lpdis)
  474. {
  475. HBRUSH hbrush;
  476. HPEN hpen_highlight, hpen_shadow, hpen_old;
  477. HDC hdc = lpdis->hDC;
  478. RECT rect;
  479. HICON hicon;
  480. HBITMAP hbitmap_old, hbitmap;
  481. BITMAP bm;
  482. int i;
  483. char buf[20];
  484.     rect = lpdis->rcItem;
  485.     if (lpdis->CtlType != ODT_BUTTON)
  486.         return FALSE;
  487.     switch (lpdis->itemAction) {
  488.         case ODA_DRAWENTIRE:
  489.         if ((hbitmap = LoadBitmap(phInstance,MAKEINTRESOURCE(lpdis->CtlID)))
  490.           != (HBITMAP)NULL) {
  491.             HDC hdcsrc = CreateCompatibleDC(hdc);
  492.             hbitmap_old = SelectObject(hdcsrc,hbitmap);
  493.             GetObject(hbitmap, sizeof(BITMAP),&bm);
  494.             if ( (rect.right-rect.left > bm.bmWidth) ||
  495.              (rect.bottom-rect.top > bm.bmHeight) ) {
  496.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  497.                 FillRect(hdc, &rect, hbrush);
  498.                 DeleteBrush(hbrush);
  499.             }
  500.             BitBlt(hdc, (rect.left+rect.right-bm.bmWidth)/2,
  501.                (rect.top+rect.bottom-bm.bmHeight)/2,
  502.                bm.bmWidth,bm.bmHeight,hdcsrc,0,0,SRCCOPY);
  503.             SelectObject(hdcsrc,hbitmap_old);
  504.             DeleteObject(hbitmap);
  505.             DeleteDC(hdcsrc);
  506.         }
  507.         else {
  508.             hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  509.             FillRect(hdc, &rect, hbrush);
  510.             DeleteBrush(hbrush);
  511.             if ((i = LoadString(phInstance, lpdis->CtlID, buf, sizeof(buf)))
  512.                 != 0) {
  513.             DWORD dw = GetTextExtent(hdc, buf, i);
  514.             SetBkMode(hdc, TRANSPARENT);
  515.             TextOut(hdc, (rect.left+rect.right-LOWORD(dw))/2,
  516.                 (rect.top+rect.bottom-HIWORD(dw))/2, buf, i);
  517.             }
  518.             else if ( (hicon = LoadIcon(phInstance, MAKEINTRESOURCE(lpdis->CtlID)))
  519.                 != (HICON)NULL )  {
  520.                 DrawIcon(hdc, (rect.left+rect.right-32)/2, 
  521.                     (rect.top+rect.bottom-32)/2, hicon);
  522.                 DestroyIcon(hicon);
  523.             }
  524.         }
  525.         hpen_old = SelectPen(hdc, GetStockObject(BLACK_PEN));
  526.         MoveTo(hdc, rect.left, rect.top);
  527.         LineTo(hdc, rect.right-1, rect.top);
  528.         LineTo(hdc, rect.right-1, rect.bottom-1);
  529.         LineTo(hdc, rect.left, rect.bottom-1);
  530.         LineTo(hdc, rect.left, rect.top-1);
  531.         SelectPen(hdc, hpen_old);
  532.         /* fall thru */
  533.         case ODA_FOCUS:
  534.         case ODA_SELECT:
  535.         if (lpdis->itemState & ODS_SELECTED) {
  536.             hpen_highlight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  537.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
  538.         }
  539.         else {
  540.             hpen_highlight = CreatePen(PS_SOLID, 1, is_win31 ? GetSysColor(COLOR_BTNHIGHLIGHT) : RGB(255,255,255));
  541.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  542.         }
  543.         hpen_old = SelectPen(hdc, hpen_highlight);
  544.         MoveTo(hdc, rect.left+1, rect.bottom-3);
  545.         LineTo(hdc, rect.left+1, rect.top+1);
  546.         LineTo(hdc, rect.right-2, rect.top+1);
  547.         MoveTo(hdc, rect.right-3, rect.top+2);
  548.         LineTo(hdc, rect.left+2, rect.top+2);
  549.         LineTo(hdc, rect.left+2, rect.bottom-4);
  550.         SelectPen(hdc, hpen_shadow);
  551.         MoveTo(hdc, rect.left+1, rect.bottom-2);
  552.         LineTo(hdc, rect.right-2, rect.bottom-2);
  553.         LineTo(hdc, rect.right-2, rect.top+1);
  554.         MoveTo(hdc, rect.right-3, rect.top+2);
  555.         LineTo(hdc, rect.right-3, rect.bottom-3);
  556.         LineTo(hdc, rect.left+2, rect.bottom-3);
  557.         SelectPen(hdc, hpen_old);
  558.         DeleteObject(hpen_highlight);
  559.         DeleteObject(hpen_shadow);
  560.             return TRUE;
  561.     }
  562.     return FALSE;
  563. }
  564.  
  565. /* returns true if cursor in client area of Ghostscript image window */
  566. BOOL
  567. in_child_client_area()
  568. {
  569. RECT rect;
  570. POINT pt;
  571. HWND hwnd;
  572.         GetCursorPos(&pt);
  573.     hwnd = WindowFromPoint(pt);
  574.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  575.         return 0;
  576.         GetClientRect(hwndimgchild, &rect);
  577.         ScreenToClient(hwndimgchild, &pt);
  578.         return PtInRect(&rect, pt);
  579. }
  580.  
  581. /* returns true if cursor in client area of Ghostview window */
  582. BOOL
  583. in_client_area()
  584. {
  585. RECT rect;
  586. POINT pt;
  587. HWND hwnd;
  588.         GetCursorPos(&pt);
  589.     hwnd = WindowFromPoint(pt);
  590.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  591.         return 0;
  592.         GetClientRect(hwndimg, &rect);
  593.         ScreenToClient(hwndimg, &pt);
  594.         return PtInRect(&rect, pt);
  595. }
  596.  
  597. /* returns true if cursor in info area or button area of Ghostview windows */
  598. BOOL
  599. in_info_area()
  600. {
  601. RECT rect;
  602. POINT pt;
  603. HWND hwnd;
  604.         GetCursorPos(&pt);
  605.     hwnd = WindowFromPoint(pt);
  606.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  607.         return 0;
  608.         ScreenToClient(hwndimg, &pt);
  609.  
  610.         GetClientRect(hwndimg, &rect);
  611.     rect.bottom = img_offset.y;
  612.     if (PtInRect(&rect, pt))
  613.         return TRUE;
  614.         GetClientRect(hwndimg, &rect);
  615.     rect.right = img_offset.x;
  616.         return PtInRect(&rect, pt);
  617. }
  618.  
  619. BOOL
  620. get_cursorpos(int *x, int *y)
  621. {
  622. RECT rect;
  623. POINT pt;
  624.     if (hwndimgchild && IsWindow(hwndimgchild)) {
  625.     GetClientRect(hwndimgchild, &rect);
  626.     GetCursorPos(&pt);
  627.     ScreenToClient(hwndimgchild, &pt);
  628.     if (PtInRect(&rect, pt)) {
  629.         *x = (int)((bitmap_scrollx+pt.x)*72.0/xdpi 
  630.         + (epsf_clipped ? doc->boundingbox[LLX] : 0));
  631.         *y = (int)(((bitmap_height-1)-(bitmap_scrolly+pt.y))*72.0/ydpi
  632.         + (epsf_clipped ? doc->boundingbox[LLY] : 0));
  633.         return TRUE;
  634.     }
  635.     }
  636.     return FALSE;
  637. }
  638.  
  639. /* paint brief info area */
  640. void
  641. info_paint(HWND hwnd)
  642. {
  643. HDC hdc;
  644. PAINTSTRUCT ps;
  645. RECT rect;
  646. int i;
  647. char buf[MAXSTR];
  648. char fmt[MAXSTR];
  649. int x, y;
  650.     hdc = BeginPaint(hwnd, &ps);
  651.     SetBkMode(hdc, TRANSPARENT);
  652.     if (info_rect.bottom) {
  653.         GetClientRect(hwnd, &rect);
  654.         rect.top = 0;
  655.         rect.left = info_rect.left;
  656.         rect.bottom = info_rect.bottom;
  657.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  658.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  659.         MoveTo(hdc, rect.left, rect.bottom);
  660.         LineTo(hdc, rect.right, rect.bottom);
  661.     }
  662.     if (button_rect.right) {
  663.         GetClientRect(hwnd, &rect);
  664.         rect.top = button_rect.top;
  665.         rect.left = button_rect.left;
  666.         rect.right = button_rect.right;
  667.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  668.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  669.         MoveTo(hdc, rect.right, rect.top);
  670.         LineTo(hdc, rect.right, rect.bottom);
  671.     }
  672.     /* write file information */
  673.     if (dfname[0] != '\0') {
  674.         i = LoadString(phInstance, IDS_FILE, buf, sizeof(buf));
  675.         GetFileTitle(dfname, buf+i, sizeof(buf)-i);
  676.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  677.         if (waiting) {
  678.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  679.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  680.         }
  681.         else {
  682.           if (doc!=(struct document *)NULL) {
  683.         int n = map_page(pagenum - 1);
  684.         i = LoadString(phInstance, IDS_PAGEINFO, fmt, sizeof(fmt));
  685.         if (doc->pages)
  686.             sprintf(buf, fmt, doc->pages[n].label ? doc->pages[n].label : " ",pagenum,  doc->numpages);
  687.         else
  688.             sprintf(buf, fmt, " " ,pagenum,  doc->numpages);
  689.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  690.           }
  691.           else {
  692.         if (is_pipe_done())
  693.             i = LoadString(phInstance, IDS_NOMORE, buf, sizeof(buf));
  694.         else {
  695.             i = LoadString(phInstance, IDS_PAGE, buf, sizeof(buf));
  696.             sprintf(buf+i, "%d", pagenum);
  697.         }
  698.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  699.           }
  700.           /* show coordinate */
  701.           if (get_cursorpos(&x, &y)) {
  702.             sprintf(buf,"%d, %d", x, y);
  703.             SetTextAlign(hdc, TA_RIGHT);
  704.             TextOut(hdc, info_coord.right-1, info_coord.top, buf, strlen(buf));
  705.           }
  706.         }
  707.     }
  708.     else {
  709.         i = LoadString(phInstance, IDS_NOFILE, buf, sizeof(buf));
  710.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  711.         if (waiting) {
  712.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  713.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  714.         }
  715.     }
  716.     EndPaint(hwnd, &ps);
  717. }
  718.  
  719. /* subclass button WndProc to give focus back to parent window */
  720. LRESULT CALLBACK _export
  721. MenuButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  722. {
  723.     switch(message) {
  724.         case WM_LBUTTONUP:
  725.         {
  726.         RECT rect;
  727.         POINT pt;
  728.         GetWindowRect(hwnd, &rect);
  729.         GetCursorPos(&pt);
  730.         if (PtInRect(&rect, pt))
  731.             SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowID(hwnd), 0L);
  732.         SetFocus(GetParent(hwnd));
  733.         }
  734.         break;
  735.     }
  736.     return CallWindowProc(lpfnButtonWndProc, hwnd, message, wParam, lParam);
  737. }
  738.  
  739.  
  740. void
  741. play_sound(int num)
  742. {
  743.     if (strlen(sound[num].file)==0)
  744.         return;
  745.     if (!is_win31 || (strcmp(sound[num].file,BEEP)==0)) {
  746.         MessageBeep(-1);
  747.         return;
  748.     }
  749.     if (is_win31) {
  750.         if (lpfnSndPlaySound != (FPSPS)NULL) 
  751.                lpfnSndPlaySound(sound[num].file, SND_SYNC);
  752.         else
  753.             MessageBeep(-1);
  754.         return;
  755.     }
  756. }
  757.  
  758. BOOL
  759. set_timer(UINT period)
  760. {
  761.     timeout_count = period;
  762.     bTimeout = FALSE;
  763.     if (SetTimer(hwndimg, ID_MYTIMER, 1000, NULL) != 0) {
  764.         bTimerSet = TRUE;
  765.         return TRUE;
  766.     }
  767.  
  768.     bTimerSet = FALSE;
  769.     gserror(IDS_NOTIMER, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  770.     return FALSE;
  771. }
  772.  
  773. void
  774. clear_timer()
  775. {
  776.     if (bTimerSet)
  777.         KillTimer(hwndimg, ID_MYTIMER);
  778.     bTimerSet = FALSE;
  779.     bTimeout = FALSE;
  780.     EnableWindow(hwndimg, TRUE);
  781. }
  782.  
  783. /* display or remove 'wait' message */
  784. void
  785. info_wait(BOOL wait)
  786. {
  787. HWND hwnd;
  788. POINT pt;
  789.     waiting = wait;
  790.     InvalidateRect(hwndimg, (LPRECT)&info_rect, FALSE);
  791.     UpdateWindow(hwndimg);
  792.  
  793.     if (waiting) {
  794.             GetCursorPos(&pt);
  795.         hwnd = WindowFromPoint(pt);
  796.         if ((hwnd == hwndimg) || IsChild(hwndimg,hwnd))
  797.         SetCursor(hcWait);
  798.     }
  799.     else {
  800.         /* set cursor to that of active window */
  801.         hwnd = GetFocus();
  802.         if ( (hwndimgchild && IsWindow(hwndimgchild))
  803.           && ((hwnd == hwndimg) || (hwnd == hwndimgchild)) ) {
  804.         if (in_child_client_area()) {
  805.             SetCursor(GetClassCursor(hwndimgchild));
  806.             return;
  807.         }
  808.         }
  809.         SetCursor(GetClassCursor(hwnd));
  810.     }
  811. }
  812.  
  813.  
  814. /* remove temporary files etc. */
  815. void
  816. gsview_close()
  817. {
  818.     gswin_close();
  819.     pipeclose();
  820.     print_cleanup();
  821.     if ((efname[0] != '\0') && !debug)
  822.         unlink(efname);
  823.     efname[0] = '\0';
  824.     if (page_list.select)
  825.         free(page_list.select);
  826.     page_list.select = NULL;
  827.     if (doc)
  828.         psfree(doc);
  829.     doc = (struct document *)NULL;
  830.     if (settings)
  831.         write_profile();
  832.     SetCursor(GetClassCursor((HWND)NULL));
  833.     return;
  834. }
  835.  
  836.  
  837. /* gsview menu commands */
  838. int
  839. gsview_command(WORD command)
  840. {
  841. char prompt[MAXSTR];        /* input dialog box prompt and message box string */
  842. char answer[MAXSTR];        /* input dialog box answer string */
  843.     if (hDlgModeless) {
  844.     play_sound(SOUND_ERROR);
  845.     return 0;    /* obtaining Bounding Box so ignore commands */
  846.     }
  847.     if (waiting) {
  848.     switch (command) {
  849. #ifdef UNUSED
  850. /* This code is supposed to allow the page skip features to be 
  851.  * used while Ghostscript is rendering a page.  However, selecting
  852.  * one of the page skip commands more than 8 times causes gsview
  853.  * to hang.
  854.  * To avoid hanging, this code is disabled.
  855.  */
  856.         case IDM_NEXT:
  857.         page_extra += 1;
  858.         return 0;
  859.         case IDM_NEXTSKIP:
  860.         page_extra += page_skip;
  861.         return 0;
  862.         case IDM_PREV:
  863.         if (doc != (struct document *)NULL)
  864.             page_extra -= 1;
  865.         else
  866.             gserror(0, (char *)0, 0, SOUND_ERROR);
  867.         return 0;
  868.         case IDM_PREVSKIP:
  869.         if (doc != (struct document *)NULL)
  870.             page_extra -= page_skip;
  871.         else
  872.             gserror(0, (char *)0, 0, SOUND_ERROR);
  873.         return 0;
  874. #endif
  875.         case IDM_INFO:
  876.         case IDM_SAVEDIR:
  877.         case IDM_SETTINGS:
  878.         case IDM_SAVESETTINGS:
  879.         case IDM_SOUNDS:
  880.         case IDM_HELPCONTENT:
  881.         case IDM_HELPSEARCH:
  882.         case IDM_ABOUT:
  883.         /* these are safe to use when busy */
  884.         break;
  885.         default:
  886.             /* if user impatient or gsview confused */
  887.             LoadString(phInstance, IDS_BUSY, prompt, sizeof(prompt));
  888.             if (MessageBox(hwndimg, prompt, szAppName, MB_YESNO | MB_ICONQUESTION) == IDYES) {
  889.                 play_sound(SOUND_ERROR);
  890.                 next_page();
  891.                 info_wait(FALSE);
  892.             }
  893.             return 0;
  894.     }
  895.     }
  896.     switch (command) {
  897.     case IDM_OPEN:
  898.         dfreopen();
  899.         gsview_display();
  900.         dfclose();
  901.         return 0;
  902.     case IDM_CLOSE:
  903.         dfreopen();
  904.         gsview_endfile();
  905.         dfname[0] = '\0';
  906.         dfclose();
  907.         if (page_list.select)
  908.             free(page_list.select);
  909.         page_list.select = NULL;
  910.         if (doc)
  911.             psfree(doc);
  912.         doc = (struct document *)NULL;
  913.             if (gswin_hinst != (HINSTANCE)NULL) {
  914.                 fprintf(cfile,"erasepage flushpage\r\n");
  915.                 set_timer(timeout);
  916.                 pipeflush();
  917.             }
  918.         info_wait(FALSE);
  919.         return 0;
  920.     case IDM_SKIP:
  921.         if (not_open())
  922.             return 0;
  923.         if (page_extra == 0) {
  924.             gserror(0, "panic", 0, SOUND_ERROR);
  925.             return 0;
  926.         }
  927.         info_wait(TRUE);
  928.         if (doc==(struct document *)NULL) {
  929.             if (!gswin_open())
  930.                 return 0;
  931.             if (is_pipe_done()) {
  932.             play_sound(SOUND_NOPAGE);
  933.             info_wait(FALSE);
  934.             }
  935.             else {
  936.             next_page();
  937.             pagenum++;
  938.             page_extra--;
  939.             }
  940.             return 0;
  941.         }
  942.         dfreopen();
  943.         dsc_skip(page_extra);
  944.         page_extra = 0;
  945.         dfclose();
  946.         return 0;
  947.     case IDM_NEXT:
  948.         if (not_open())
  949.             return 0;
  950.         info_wait(TRUE);
  951.         if (doc==(struct document *)NULL) {
  952.             if (!gswin_open())
  953.                 return 0;
  954.             if (is_pipe_done()) {
  955.             play_sound(SOUND_NOPAGE);
  956.             info_wait(FALSE);
  957.             }
  958.             else {
  959.             pagenum++;
  960.             next_page();
  961.             }
  962.             return 0;
  963.         }
  964.         dfreopen();
  965.         dsc_skip(1+page_extra);
  966.         page_extra = 0;
  967.         dfclose();
  968.         return 0;
  969.     case IDM_NEXTSKIP:
  970.         if (not_dsc())
  971.             return 0;
  972.         dfreopen();
  973.         dsc_skip(page_skip+page_extra);
  974.         page_extra = 0;
  975.         dfclose();
  976.         return 0;
  977.     case IDM_REDISPLAY:
  978.         if (not_open())
  979.             return 0;
  980.         info_wait(TRUE);
  981.         if (doc==(struct document *)NULL) {
  982.             /* don't know where we are so close and reopen */
  983.             if (!is_pipe_done())
  984.             gswin_close();
  985.         }
  986.         if (!gswin_open())
  987.             return 0;
  988.         info_wait(TRUE);
  989.         if (page_ready)
  990.             next_page(); 
  991.         dfreopen();
  992.         if ((doc==(struct document *)NULL) || (doc->pages==0)) {
  993.             gsview_displayfile(dfname);
  994.             dfclose();
  995.             return 0;
  996.         }
  997.         dsc_dopage();
  998.         dfclose();
  999.         return 0;
  1000.     case IDM_PREV:
  1001.         if (not_dsc())
  1002.             return 0;
  1003.         dfreopen();
  1004.         dsc_skip(-1+page_extra);
  1005.         page_extra = 0;
  1006.         dfclose();
  1007.         return 0;
  1008.     case IDM_PREVSKIP:
  1009.         if (not_dsc())
  1010.             return 0;
  1011.         dfreopen();
  1012.         dsc_skip(-page_skip+page_extra);
  1013.         page_extra = 0;
  1014.         dfclose();
  1015.         return 0;
  1016.     case IDM_GOTO:
  1017.         if (not_dsc())
  1018.             return 0;
  1019.         dfreopen();
  1020.         if (doc->numpages == 0) {
  1021.             gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  1022.         }
  1023.         else if (get_page(&pagenum, FALSE)) {
  1024.             if (pagenum > doc->numpages) {
  1025.             pagenum = doc->numpages;
  1026.             play_sound(SOUND_NOPAGE);
  1027.             }
  1028.             else if (pagenum < 1) {
  1029.             pagenum = 1;
  1030.             play_sound(SOUND_NOPAGE);
  1031.             }
  1032.             else {
  1033.             if (gswin_open()) {
  1034.                 info_wait(TRUE);
  1035.                 if (page_ready)
  1036.                     next_page();
  1037.                 dsc_dopage();
  1038.             }
  1039.             }
  1040.         }
  1041.         dfclose();
  1042.         return 0;
  1043.     case IDM_INFO:
  1044.         {
  1045.         DLGPROC lpProcInfo;
  1046.         lpProcInfo = (DLGPROC)MakeProcInstance((FARPROC)InfoDlgProc, phInstance);
  1047.         DialogBoxParam( phInstance, "InfoDlgBox", hwndimg, lpProcInfo, (LPARAM)NULL);
  1048.         FreeProcInstance((FARPROC)lpProcInfo);
  1049.         }
  1050.         return 0;
  1051.     case IDM_SELECT:
  1052.         gsview_select();
  1053.         dfclose();
  1054.         return 0;
  1055.     case IDM_PRINT:
  1056.         if (dfname[0] == '\0')
  1057.             gsview_select();
  1058.         dfreopen();
  1059.         if (dfname[0] != '\0')
  1060.             gsview_print(FALSE);
  1061.         dfclose();
  1062.         return 0;
  1063.     case IDM_PRINTTOFILE:
  1064.         if (dfname[0] == '\0')
  1065.             gsview_select();
  1066.         dfreopen();
  1067.         if (dfname[0] != '\0')
  1068.             gsview_print(TRUE);
  1069.         dfclose();
  1070.         return 0;
  1071.     case IDM_SPOOL:
  1072.         gsview_spool((char *)NULL, (char *)NULL);
  1073.         return 0;
  1074.     case IDM_EXTRACT:
  1075.         if (dfname[0] == '\0')
  1076.             gsview_select();
  1077.         dfreopen();
  1078.         if (dfname[0] != '\0')
  1079.             gsview_extract();
  1080.         dfclose();
  1081.         return 0;
  1082.     case IDM_EXIT:
  1083.         PostQuitMessage(0);
  1084.         return 0;
  1085.     case IDM_COPYCLIP:
  1086.         if (hwndimgchild && IsWindow(hwndimgchild))
  1087.             SendMessage(hwndimgchild, WM_GSVIEW, COPY_CLIPBOARD, NULL);
  1088.         return 0;
  1089.     case IDM_PASTETO:
  1090.         clip_to_file();
  1091.         return 0;
  1092.     case IDM_CONVERT:
  1093.         clip_convert();
  1094.         return 0;
  1095.     case IDM_GSCOMMAND:
  1096.         LoadString(phInstance, IDS_GSCOMMAND, prompt, sizeof(prompt));
  1097.         strcpy(answer, szGSwin);
  1098.         LoadString(phInstance, IDS_TOPICGSCMD, szHelpTopic, sizeof(szHelpTopic));
  1099.         if (get_string(prompt,answer))
  1100.             strcpy(szGSwin, answer);
  1101.         if (szGSwin[0]=='\0')
  1102.             strcpy(szGSwin, DEFAULT_GSCOMMAND);
  1103.         return 0;
  1104.     case IDM_SAFER:
  1105.         safer = !safer;
  1106.         CheckMenuItem(hmenu, IDM_SAFER, MF_BYCOMMAND | 
  1107.             (safer ? MF_CHECKED : MF_UNCHECKED));
  1108.         return 0;
  1109.     case IDM_SAVEDIR:
  1110.         save_dir = !save_dir;
  1111.         CheckMenuItem(hmenu, IDM_SAVEDIR, MF_BYCOMMAND | 
  1112.             (save_dir ? MF_CHECKED : MF_UNCHECKED));
  1113.         return 0;
  1114.     case IDM_BUTTONSHOW:
  1115.         button_show = !button_show;
  1116.         CheckMenuItem(hmenu, IDM_BUTTONSHOW, MF_BYCOMMAND | 
  1117.             (button_show ? MF_CHECKED : MF_UNCHECKED));
  1118.         show_buttons();
  1119.         return 0;
  1120.     case IDM_QUICK:
  1121.         quick = !quick;
  1122.         CheckMenuItem(hmenu, IDM_QUICK, MF_BYCOMMAND | 
  1123.             (quick ? MF_CHECKED : MF_UNCHECKED));
  1124.         return 0;
  1125.     case IDM_AUTOREDISPLAY:
  1126.         redisplay = !redisplay;
  1127.         CheckMenuItem(hmenu, IDM_AUTOREDISPLAY, MF_BYCOMMAND | 
  1128.             (redisplay ? MF_CHECKED : MF_UNCHECKED));
  1129.         return 0;
  1130.     case IDM_EPSFCLIP:
  1131.         epsf_clip = !epsf_clip;
  1132.         CheckMenuItem(hmenu, IDM_EPSFCLIP, MF_BYCOMMAND | 
  1133.             (epsf_clip ? MF_CHECKED : MF_UNCHECKED));
  1134.         gswin_resize();
  1135.         return 0;
  1136.     case IDM_EPSFWARN:
  1137.         epsf_warn = !epsf_warn;
  1138.         CheckMenuItem(hmenu, IDM_EPSFWARN, MF_BYCOMMAND | 
  1139.             (epsf_warn ? MF_CHECKED : MF_UNCHECKED));
  1140.         return 0;
  1141.     case IDM_PSTOEPS:
  1142.         if (dfname[0] == '\0')
  1143.             gsview_display();
  1144.         if (dfname[0] != '\0') {
  1145.             dfreopen();
  1146.             ps_to_eps();
  1147.             dfclose();
  1148.         }
  1149.         return 0;
  1150.     case IDM_MAKEEPSI:
  1151.         dfreopen();
  1152.         make_eps_interchange();
  1153.         dfclose();
  1154.         return 0;
  1155.     case IDM_MAKEEPST4:
  1156.     case IDM_MAKEEPST:
  1157.         dfreopen();
  1158.         make_eps_tiff(command);
  1159.         dfclose();
  1160.         return 0;
  1161.     case IDM_MAKEEPSW:
  1162.         dfreopen();
  1163.         make_eps_metafile();
  1164.         dfclose();
  1165.         return 0;
  1166.     case IDM_EXTRACTPS:
  1167.     case IDM_EXTRACTPRE:
  1168.         dfreopen();
  1169.         extract_doseps(command);
  1170.         dfclose();
  1171.         return 0;
  1172.     case IDM_SETTINGS:
  1173.         write_profile();
  1174.         return 0;
  1175.     case IDM_SAVESETTINGS:
  1176.         if (settings) 
  1177.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_UNCHECKED);
  1178.         else
  1179.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_CHECKED);
  1180.         settings = !settings;
  1181.         sprintf(prompt, "%d", settings);
  1182.         WritePrivateProfileString(INISECTION, "SaveSettings", prompt, INIFILE);
  1183.         return 0;
  1184.     case IDM_SOUNDS:
  1185.         {
  1186.         DLGPROC lpProcSound;
  1187.         LoadString(phInstance, IDS_TOPICSOUND, szHelpTopic, sizeof(szHelpTopic));
  1188.         lpProcSound = (DLGPROC)MakeProcInstance((FARPROC)SoundDlgProc, phInstance);
  1189.         DialogBoxParam( phInstance, "SoundDlgBox", hwndimg, lpProcSound, (LPARAM)NULL);
  1190.         FreeProcInstance((FARPROC)lpProcSound);
  1191.         }
  1192.         return 0;
  1193.     case IDM_PORTRAIT:
  1194.     case IDM_LANDSCAPE:
  1195.     case IDM_UPSIDEDOWN:
  1196.     case IDM_SEASCAPE:
  1197.     case IDM_SWAPLANDSCAPE:
  1198.         dfreopen();
  1199.         gsview_orientation(command);
  1200.         dfclose();
  1201.         return 0;
  1202.     case IDM_RESOLUTION:
  1203.         LoadString(phInstance, IDS_RES, prompt, sizeof(prompt));
  1204.         if (xdpi == ydpi)
  1205.             sprintf(answer,"%g", xdpi);
  1206.         else 
  1207.             sprintf(answer,"%g %g", xdpi, ydpi);
  1208.         LoadString(phInstance, IDS_TOPICMEDIA, szHelpTopic, sizeof(szHelpTopic));
  1209.         if (get_string(prompt,answer)) {
  1210.             switch (sscanf(answer,"%f %f", &xdpi, &ydpi)) {
  1211.               case EOF:
  1212.               case 0:
  1213.             return 0;
  1214.               case 1:
  1215.             ydpi = xdpi;
  1216.               case 2:
  1217.             if (xdpi==0.0)
  1218.                 xdpi = DEFAULT_RESOLUTION;
  1219.             if (ydpi==0.0)
  1220.                 ydpi = DEFAULT_RESOLUTION;
  1221.             dfreopen();
  1222.             gswin_resize();
  1223.             dfclose();
  1224.             }
  1225.         }
  1226.         return 0;
  1227.     case IDM_LETTER:
  1228.     case IDM_LETTERSMALL:
  1229.     case IDM_TABLOID:
  1230.     case IDM_LEDGER:
  1231.     case IDM_LEGAL:
  1232.     case IDM_STATEMENT:
  1233.     case IDM_EXECUTIVE:
  1234.     case IDM_A3:
  1235.     case IDM_A4:
  1236.     case IDM_A4SMALL:
  1237.     case IDM_A5:
  1238.     case IDM_B4:
  1239.     case IDM_B5:
  1240.     case IDM_FOLIO:
  1241.     case IDM_QUARTO:
  1242.     case IDM_10X14:
  1243.     case IDM_USERSIZE:
  1244.         if (command == IDM_USERSIZE)
  1245.             if (!gsview_usersize())
  1246.             return 0;
  1247.         dfreopen();
  1248.         gsview_media(command);
  1249.         dfclose();
  1250.         return 0;
  1251.     case IDM_HELPCONTENT:
  1252.         WinHelp(hwndimg,szHelpName,HELP_CONTENTS,(DWORD)NULL);
  1253.         return 0;
  1254.     case IDM_HELPSEARCH:
  1255.         WinHelp(hwndimg,szHelpName,HELP_PARTIALKEY,(DWORD)"");
  1256.         return 0;
  1257.     case IDM_ABOUT:
  1258.         {
  1259.         DLGPROC lpProcAbout;
  1260.         lpProcAbout = (DLGPROC)MakeProcInstance((FARPROC)AboutDlgProc, phInstance);
  1261.         DialogBoxParam( phInstance, "AboutDlgBox", hwndimg, lpProcAbout, (LPARAM)NULL);
  1262.         FreeProcInstance((FARPROC)lpProcAbout);
  1263.         }
  1264.         return 0;
  1265.     }
  1266.     return 0;
  1267. }
  1268.  
  1269. /* if no document open, display error message and return true */
  1270. BOOL
  1271. not_open()
  1272. {
  1273.     if (dfname[0] != '\0')
  1274.         return FALSE;
  1275.     gserror(IDS_NOTOPEN, NULL, MB_ICONEXCLAMATION, SOUND_NOTOPEN);
  1276.     return TRUE;
  1277. }
  1278.  
  1279. /* if not DSC document or not open, display error message and return true */
  1280. BOOL
  1281. not_dsc()
  1282. {
  1283.     if (not_open())
  1284.         return TRUE;
  1285.     if (doc!=(struct document *)NULL)
  1286.         return FALSE;
  1287.     gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  1288.     return TRUE;
  1289. }
  1290.  
  1291. void
  1292. gserror(UINT id, char *str, UINT icon, int sound)
  1293. {
  1294. int i;
  1295. char mess[300];
  1296.     if (sound >= 0)
  1297.         play_sound(sound);
  1298.     i = 0;
  1299.     if (id)
  1300.         i = LoadString(phInstance, id, mess, sizeof(mess)-1);
  1301.     mess[i] = '\0';
  1302.     if (str)
  1303.         strncpy(mess+i, str, sizeof(mess)-i-1);
  1304.     MessageBox(hwndimg, mess, szAppName, icon | MB_OK);
  1305. }
  1306.  
  1307. /* for ps.c errors instead of fprintf(stderr,...)! */
  1308. void
  1309. pserror(char *str)
  1310. {
  1311.     MessageBox(hwndimg,str,szAppName, MB_OK | MB_ICONHAND);
  1312. }
  1313.